/*
 *   Copyright (c) 2010-2022, SIUFUNG
 */
package net.siufung.market.base.tenant.service.impl;

import cn.hutool.core.util.IdUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import net.siufung.core.exception.BizServiceException;
import net.siufung.core.model.enums.DeletedEnum;
import net.siufung.core.model.enums.InitializeEnum;
import net.siufung.market.base.tenant.api.ITenantUserApi;
import net.siufung.market.base.tenant.api.dto.TenantUserCreateDto;
import net.siufung.market.base.tenant.api.dto.TenantUserUpdateDto;
import net.siufung.market.base.tenant.mapper.ITenantMapper;
import net.siufung.market.base.tenant.mapper.entity.Tenant;
import net.siufung.market.base.tenant.mapper.entity.TenantMenu;
import net.siufung.market.base.tenant.mapper.entity.TenantProfile;
import net.siufung.market.base.tenant.mapper.entity.TenantQuota;
import net.siufung.market.base.tenant.service.ITenantMenuService;
import net.siufung.market.base.tenant.service.ITenantProfileService;
import net.siufung.market.base.tenant.service.ITenantQuotaService;
import net.siufung.market.base.tenant.service.ITenantService;
import net.siufung.mybatis.base.BaseServiceImpl;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import java.io.Serializable;
import java.util.List;
import java.util.Objects;

/**
 * 系统租户表 数据服务实现
 *
 * @author 陈建峰
 * @since 2022-07-06 14:45:08
 */
@Slf4j
@AllArgsConstructor
@Service(value = "tenantService")
@Transactional(rollbackFor = Exception.class)
public class TenantServiceImpl extends BaseServiceImpl<ITenantMapper, Tenant> implements ITenantService {

    private final ITenantProfileService tenantProfileService;
    private final ITenantQuotaService tenantQuotaService;
    private final ITenantMenuService tenantMenuService;
    private final ITenantUserApi tenantUserApi;

    @Override
    public Boolean save(Tenant tenant, TenantProfile tenantProfile) {
        if(Objects.isNull(tenant.getCode())){
            tenant.setCode(IdUtil.fastSimpleUUID());
        }
        if(super.save(tenant)){
            if(!Objects.isNull(tenantProfile)){
                tenantProfile.setId(tenant.getId());
                tenantProfileService.save(tenantProfile);
            }
            TenantUserCreateDto tenantUserCreateDto = new TenantUserCreateDto();
            tenantUserCreateDto.setTenantId(tenant.getId());
            tenantUserCreateDto.setContacts(tenantProfile.getContacts());
            tenantUserCreateDto.setPhone(tenantProfile.getPhone());
            if(Objects.nonNull(tenantUserApi)){
                tenantUserCreateDto = tenantUserApi.createUserByTenant(tenantUserCreateDto);
                if(Objects.nonNull(tenantUserCreateDto)){
                    tenant.setAdminAccount(tenantUserCreateDto.getLoginName());
                    tenant.setAdminAccountId(tenantUserCreateDto.getUserId());
                    super.updateById(tenant);
                }
            }
            return Boolean.TRUE;
        };
        return Boolean.FALSE;
    }

    @Override
    public Boolean save(Tenant tenant, TenantProfile tenantProfile, List<TenantQuota> tenantQuotaList) {
        if(CollectionUtils.isEmpty(tenantQuotaList)){
            throw new BizServiceException("租户配额列表不能为空！");
        }
        if(this.save(tenant, tenantProfile)){
            return tenantQuotaService.saveBatch(tenantQuotaList);
        }
        return Boolean.FALSE;
    }

    @Override
    public Boolean updateById(Tenant tenant, TenantProfile tenantProfile) {
        if(super.updateById(tenant)){
            if(Objects.nonNull(tenantProfile)){
                tenantProfileService.updateById(tenantProfile);
                if(InitializeEnum.NOT.getValue().equals(tenant.getTenantInitState())){
                    TenantUserUpdateDto tenantUserUpdateDto = new TenantUserUpdateDto();
                    tenantUserUpdateDto.setContacts(tenantProfile.getContacts());
                    tenantUserUpdateDto.setPhone(tenantProfile.getPhone());
                    tenantUserUpdateDto.setUserId(tenant.getAdminAccountId());
                    if(Objects.nonNull(tenantUserApi)) {
                        tenantUserApi.updateUserByTenant(tenantUserUpdateDto);
                    }
                }
            }
            return Boolean.TRUE;
        }
        return Boolean.FALSE;
    }

    @Override
    public boolean updateStatusById(Serializable id, DeletedEnum deletedEnum) {
        if(super.update(
                new LambdaUpdateWrapper<Tenant>()
                        .eq(Tenant::getId, id)
                        .set(Tenant::getDeleted, deletedEnum.getValue()))){
            tenantQuotaService.update(
                    new LambdaUpdateWrapper<TenantQuota>()
                        .eq(TenantQuota::getTenantId, id)
                        .set(TenantQuota::getDeleted, deletedEnum.getValue()));
            tenantMenuService.update(
                    new LambdaUpdateWrapper<TenantMenu>()
                        .eq(TenantMenu::getTenantId, id)
                        .set(TenantMenu::getDeleted, deletedEnum.getValue()));
            if(Objects.nonNull(tenantUserApi)) {
                tenantUserApi.updateUserStatusById(id, deletedEnum);
            }
            return Boolean.TRUE;
        }
        return Boolean.FALSE;
    }

    @Override
    public boolean removeById(Serializable id) {
        if(super.removeById(id)){
            tenantProfileService.removeById(id);
            tenantQuotaService.remove(
                    new LambdaQueryWrapper<TenantQuota>()
                        .eq(TenantQuota::getTenantId, id));
            tenantMenuService.remove(
                    new LambdaUpdateWrapper<TenantMenu>()
                        .eq(TenantMenu::getTenantId, id));

            if(Objects.nonNull(tenantUserApi)) {
                tenantUserApi.removeUserListById(id);
            }
            return Boolean.TRUE;
        };
        return Boolean.FALSE;
    }

}